package server;




import game.GameServer;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

import universe.MessageFromClient;
import constants.Constants;
import constants.Message;



public class ServerMGL {

static final int PUERTO=4999; //puerto en el cual escucho a los clientes
	
	ArrayList<Client> listaClientes;
	
	GameServer game = null;
	
	
	
	public ServerMGL(GameServer game){
		this.game=game;
		System.out.println("Escucho en el puerto :"+PUERTO);
		listaClientes = new ArrayList<Client>();
		
		try {
			//Creo un socket que escucha a los clientes en  PUERTO
			ServerSocket skServidor = new ServerSocket( PUERTO );
			
			Runnable hablaCliente = new HiloHablaClientes();
			Thread hiloHabla = new Thread(hablaCliente);
			hiloHabla.start();	
			
			//se crea un ciclo permanente para escuchar a todos los clientes que lleguen
			while(true){
				//se crea un socket por cada cliente que llegue y se crea un hilo que lo atienda
				Socket skCliente = skServidor.accept();
				//agrego el nuevo cliente la lista de clientes
				Client client = new Client(skCliente);
				listaClientes.add(client);
			
				
				Runnable nuevoCliente = new HiloAtiendeCliente(client);
				Thread hilo = new Thread(nuevoCliente);
				hilo.start();
				
				
				
				System.out.println("LLEGO UN CLIENTE");
				
			}
	
		} 
		catch( Exception e ) {
	
			System.out.println( e.getMessage() );
	
		}
		
		
	}
	public class HiloHablaClientes implements Runnable {
		@Override
		public void run() {
			double contTime=0;
			try {
				double tiempo = System.currentTimeMillis();
				while(true){
					
					Thread.sleep(20);
					//tiempo = (System.currentTimeMillis()-tiempo)/1000f;
					tiempo=System.currentTimeMillis()-tiempo;
					game.update(tiempo);
					
					//TODO OJOOO
					
					contTime=contTime+tiempo;
					if(contTime<80){
						tiempo = System.currentTimeMillis();
						//System.out.println("Contime "+contTime);
						continue;
					} 
					//System.out.println("Contime "+tiempo);
					contTime=0;
					DataOutputStream flujoSalida;
					ArrayList<Client> clientList = (ArrayList<Client>) listaClientes.clone();
					
					for(Client client: clientList){
						//System.out.println(client.getId());
						
						if(client.getId()!=Constants.NO_CLIENT_ID){
							OutputStream aux = client.getSocket().getOutputStream();
							flujoSalida= new DataOutputStream( aux );
							
							flujoSalida.writeUTF(game.getMessageUpdateWorld(client.getUniverseId()));
							
							
							ArrayList<MessageFromClient> listMessage = game.getMessageFor(client.getId(),client.getUniverseId());
							for(MessageFromClient msg : listMessage){
								flujoSalida.writeUTF(msg.getMessage());
							}
						}
					
					}
				
					tiempo = System.currentTimeMillis();		
					
				}
				
			} catch (InterruptedException e) {
 
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	
	
	private class HiloAtiendeCliente implements Runnable{
		
		int head;	
		Client client= new Client();
		
		public HiloAtiendeCliente(Client client){
		
			this.client= client;				

		}
		@Override
		public void run() {
			
			//creo un lazo que esta continuamente esperando mensajes del cliente al que atiende
			while(true){
				try {
					System.out.println("Espero Mensaje Del Cliente");
					//asumo que los mensajes se envian en este orden, primero x y luego y
					
					
					String msg = client.read();  
							
					String splt[]=msg.split(System.getProperty("line.separator"));
					head=Integer.parseInt(splt[0]);
					
					//System.out.println(msg);
					switch(head){
					case Message.ASK_FOR_ACTION_FROM_OBJECT:
						System.out.println("ME PREGUNTA POR AGENTES DEL OBJETO");
						int objectId = Integer.parseInt(splt[1]);
						client.write(game.getMessageAgentsFromObject(objectId,client.getId(),client.getUniverseId()));
						
					break;
					case Message.ASK_FOR_ACTION_FROM_OBJECT_INVENTORY:
						System.out.println("ME PREGUNTA POR AGENTES DEL OBJETO INVENTORY");
						client.write(game.getMessageAgentsFromObject(splt[1],client.getId(),client.getUniverseId()));
					break;
					case Message.ASK_FOR_PARAMETERS:
						System.out.println("ME PREGUNTA POR PARAMTROS DEL AGENTE "+msg);
						System.out.println("Me preguntan por parametros "+game.getParameters(splt[1],client.getUniverseId())+":MM");
						client.write(game.getParameters(splt[1],client.getUniverseId()));
						
					break;
					case Message.SEND_PARAMETERS_FOR_AGENT:
						System.out.println("RECIBO PARAMETROS SERVIDOr "+splt[1]);
						game.setParameters(splt[1],client.getUniverseId());
						System.out.println(splt[1]);
					break;
					case Message.CONNECTION_ID:
						client.setId(Integer.parseInt(splt[1]));
						System.out.println("intenta conectarse enviandome su id" + client.getId());
						
						String mes = Message.CONNECTION_ACCEPTED+System.getProperty("line.separator");
						client.write(mes);
						int universeId ;
						universeId= game.connectClient(client.getId());
						client.setUniverseId(universeId);
						mes = Message.BACKGROUND_OBJECT+System.getProperty("line.separator");
						client.write(game.getBackgroundObject(mes,client.getUniverseId()));
						System.out.println("BACKGROUND "+mes);
						
					break;
					case Message.REQUEST_INVENTORY:
						//System.out.println("Este es el inventario : "+game.getInventory(splt[1],idCliente));
						client.write(game.getInventory(splt[1],client.getId(),client.getUniverseId()));
						
					break;
					case Message.CLIENT_UNIVERSE_TRANSPORT:
						int id = Integer.parseInt(splt[1]);
						client.setUniverseId(id);
						mes = Message.BACKGROUND_OBJECT+System.getProperty("line.separator");
						client.write(game.getBackgroundObject(mes,client.getUniverseId()));
						
					break;
					
					default:
						System.out.println("CABECERA DE MENSAJE DESCONOCIDA  Servidor");
					
					}	
					
				
				
					
					//despues de recibir una actualizacion , actualizo a todos los demas clientes
					//actualizarClientes(idCliente);
					
				} catch (Exception e) {
					
					//e.printStackTrace();
					System.err.println("SE DESCONECTO EL CLIENTE: "+client.getId());
					listaClientes.remove(client);
					game.disconnectClient(client.getId(),client.getUniverseId());
					return;
				}
			}
			
		}
	}
	
	/*public static void main(String[] args) {
		
		new ServerMGL();
		
	}*/

	

}
